package com.lin.netty.module.eventLoop;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import lombok.extern.slf4j.Slf4j;

/**
 * EventLoop处理io事件
 *
 * EventLoop细分1：boss和worker
 * EventLoop细分2：EventLoop的某个handler执行耗时太长的话，会影响EventLoop绑定的其他channel的读写事件，
 * 可以将耗时将长的操作交给DefaultEventLoop执行，这样EventLoop就可以去处理其他其他channel的IO事件。
 *
 * 如果两个handler是同一个线程，则一个handler执行完直接同步调用下一个handler执行。如果不是同一个线程，则一个handler执行完，则将处理交个下一个handler的线程异步执行。
 *
 */
@Slf4j
public class EventLoopServer {
    public static void main(String[] args) {
        // EventLoop细分1：boss和worker
        NioEventLoopGroup boss = new NioEventLoopGroup(); // boss处理ServerSocketChannel上的accept事件
        NioEventLoopGroup workers = new NioEventLoopGroup(1); // worker处理SocketChannel上的读写事件

        // EventLoop细分2：EventLoop的某个handler执行耗时太长的话，会影响EventLoop绑定的其他channel的读写事件，
        // 可以将耗时将长的操作交给DefaultEventLoop执行，这样EventLoop就可以去处理其他其他channel的IO事件
        DefaultEventLoopGroup defaultEventLoopGroup = new DefaultEventLoopGroup();

        new ServerBootstrap()
                .group(boss, workers)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast("handler1", new SimpleChannelInboundHandler<String>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
                                ctx.fireChannelRead(msg);
                                log.debug("handler1");
                                // 模拟handler耗时太长 交给DefaultEventLoop执行
//                                Thread.sleep(10000);
//
//                                log.debug(msg);
                            }
                        }).addLast(defaultEventLoopGroup, "handler2", new SimpleChannelInboundHandler<String>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
                                // 模拟handler耗时太长
                                Thread.sleep(10000);

                                log.debug(msg);
                            }
                        });
                    }
                })
                .bind(1122);
    }
}
